package com.kite.music;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
import org.json.JSONObject;
import org.json.JSONArray;

public class NetUtil {
    private static final String TAG = "NetUtil";
    private WeakReference<WebView> webviewRef;
    private WeakReference<Activity> activityRef;
    private WeakReference<Context> contextRef;
    private static final ExecutorService NETWORK_EXECUTOR = Executors.newFixedThreadPool(3);

    // 使用Android内置的URL模式验证
    private static final Pattern URL_PATTERN = android.util.Patterns.WEB_URL;

    // 网络请求缓存相关
    private final Map<String, CachedResponse> responseCache = new ConcurrentHashMap<>();
    private final AtomicInteger totalRequests = new AtomicInteger(0);
    private final AtomicInteger cacheHits = new AtomicInteger(0);
    private final AtomicLong lastCleanupTime = new AtomicLong(System.currentTimeMillis());

    // 缓存配置
    private static final int MAX_CACHE_SIZE = 100;
    private static final long CACHE_EXPIRY_TIME = 5 * 60 * 1000; // 5分钟
    private static final long CLEANUP_INTERVAL = 10 * 60 * 1000; // 10分钟清理一次

    public NetUtil(WebView webview, Activity activity, Context context) {
        this.webviewRef = new WeakReference<>(webview);
        this.activityRef = new WeakReference<>(activity);
        this.contextRef = new WeakReference<>(context);
    }

    // 是否为有效的URL
    public boolean isValidUrl(String urlStr) {
        return urlStr != null && URL_PATTERN.matcher(urlStr).matches();
    }

    // 检查网络权限
    private boolean hasNetworkPermission() {
        Context context = contextRef.get();
        if (context == null) return false;

        return context.checkCallingOrSelfPermission("android.permission.INTERNET") == PackageManager.PERMISSION_GRANTED;
    }

    // 异步GET请求
    @JavascriptInterface
    public void getAsync(final String urlString, final String callbackFunction) {
        if (!hasNetworkPermission()) {
            callJavaScriptCallback(callbackFunction, "{\"error\":\"No internet permission\"}");
            return;
        }

        NETWORK_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                final String result = getSync(urlString);
                callJavaScriptCallback(callbackFunction, result);
            }
        });
    }

    // 带缓存的异步GET请求 - 新增功能
    @JavascriptInterface
    public void getCachedAsync(final String urlString, final long maxAge, final String callbackFunction) {
        if (!hasNetworkPermission()) {
            callJavaScriptCallback(callbackFunction, "{\"error\":\"No internet permission\"}");
            return;
        }

        NETWORK_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    totalRequests.incrementAndGet();

                    // 检查缓存
                    CachedResponse cached = responseCache.get(urlString);
                    if (cached != null && !cached.isExpired(maxAge)) {
                        cacheHits.incrementAndGet();
                        callJavaScriptCallback(callbackFunction, cached.getData());
                        return;
                    }

                    // 发起网络请求
                    final String result = getSync(urlString);

                    // 缓存成功响应
                    if (result != null && !result.contains("\"error\"")) {
                        responseCache.put(urlString, new CachedResponse(result, System.currentTimeMillis()));

                        // 定期清理过期缓存
                        if (System.currentTimeMillis() - lastCleanupTime.get() > CLEANUP_INTERVAL) {
                            cleanupExpiredCache();
                        }
                    }

                    callJavaScriptCallback(callbackFunction, result);
                } catch (Exception e) {
                    Log.e(TAG, "Cached GET request failed", e);
                    callJavaScriptCallback(callbackFunction, "{\"error\":\"" + escapeJsonString(e.getMessage()) + "\"}");
                }
            }
        });
    }

    // 带缓存的同步GET请求
    @JavascriptInterface
    public String getCachedSync(String urlString, long maxAge) {
        if (!isValidUrl(urlString)) {
            return "{\"error\":\"Invalid URL\"}";
        }

        totalRequests.incrementAndGet();

        // 检查缓存
        CachedResponse cached = responseCache.get(urlString);
        if (cached != null && !cached.isExpired(maxAge)) {
            cacheHits.incrementAndGet();
            return cached.getData();
        }

        // 发起网络请求并缓存结果
        String result = getSync(urlString);
        if (result != null && !result.contains("\"error\"")) {
            responseCache.put(urlString, new CachedResponse(result, System.currentTimeMillis()));

            // 定期清理过期缓存
            if (System.currentTimeMillis() - lastCleanupTime.get() > CLEANUP_INTERVAL) {
                cleanupExpiredCache();
            }
        }

        return result;
    }

    // 同步GET请求（需要在后台线程调用）
    @JavascriptInterface
    public String getSync(String urlString) {
        if (!isValidUrl(urlString)) {
            return "{\"error\":\"Invalid URL\"}";
        }

        HttpURLConnection connection = null;
        BufferedReader reader = null;
        StringBuilder result = new StringBuilder();

        try {
            URL url = new URL(urlString);
            connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法和请求头
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("Accept-Charset", "UTF-8");
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(10000);

            // 处理重定向
            connection.setInstanceFollowRedirects(true);

            // 读取响应
            int responseCode = connection.getResponseCode();
            String contentType = connection.getContentType();

            if (responseCode >= 200 && responseCode < 300) {
                InputStream inputStream = connection.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));

                String line;
                while ((line = reader.readLine()) != null) {
                    result.append(line);
                }

                // 检查是否为JSON响应
                if (contentType != null && !contentType.contains("application/json") &&
                        !contentType.contains("text/json")) {
                    // 非JSON响应，包装为JSON
                    return "{\"content\":\"" + escapeJsonString(result.toString()) +
                            "\", \"contentType\":\"" + contentType + "\"}";
                }
            } else {
                return "{\"error\":\"HTTP " + responseCode + "\", \"message\":\"" +
                        escapeJsonString(connection.getResponseMessage()) + "\"}";
            }
        } catch (Exception e) {
            Log.e(TAG, "GET request failed", e);
            return "{\"error\":\"" + escapeJsonString(e.getMessage()) + "\"}";
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (connection != null) {
                    connection.disconnect();
                }
            } catch (Exception e) {
                Log.e(TAG, "Error closing resources", e);
            }
        }

        return result.toString();
    }

    // 异步POST请求
    @JavascriptInterface
    public void postAsync(final String urlString, final String postData, final String callbackFunction) {
        if (!hasNetworkPermission()) {
            callJavaScriptCallback(callbackFunction, "{\"error\":\"No internet permission\"}");
            return;
        }

        NETWORK_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                final String result = postSync(urlString, postData);
                callJavaScriptCallback(callbackFunction, result);
            }
        });
    }

    // 同步POST请求（需要在后台线程调用）
    @JavascriptInterface
    public String postSync(String urlString, String postData) {
        if (!isValidUrl(urlString)) {
            return "{\"error\":\"Invalid URL\"}";
        }

        HttpURLConnection connection = null;
        BufferedReader reader = null;
        StringBuilder result = new StringBuilder();

        try {
            URL url = new URL(urlString);
            connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法和请求头
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("Accept-Charset", "UTF-8");
            connection.setDoOutput(true);
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(10000);
            connection.setInstanceFollowRedirects(true);

            // 写入POST数据
            if (postData != null) {
                OutputStream os = connection.getOutputStream();
                os.write(postData.getBytes("UTF-8"));
                os.close();
            }

            // 读取响应
            int responseCode = connection.getResponseCode();
            String contentType = connection.getContentType();

            if (responseCode >= 200 && responseCode < 300) {
                InputStream inputStream = connection.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));

                String line;
                while ((line = reader.readLine()) != null) {
                    result.append(line);
                }

                // 检查是否为JSON响应
                if (contentType != null && !contentType.contains("application/json") &&
                        !contentType.contains("text/json")) {
                    // 非JSON响应，包装为JSON
                    return "{\"content\":\"" + escapeJsonString(result.toString()) +
                            "\", \"contentType\":\"" + contentType + "\"}";
                }
            } else {
                return "{\"error\":\"HTTP " + responseCode + "\", \"message\":\"" +
                        escapeJsonString(connection.getResponseMessage()) + "\"}";
            }
        } catch (Exception e) {
            Log.e(TAG, "POST request failed", e);
            return "{\"error\":\"" + escapeJsonString(e.getMessage()) + "\"}";
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (connection != null) {
                    connection.disconnect();
                }
            } catch (Exception e) {
                Log.e(TAG, "Error closing resources", e);
            }
        }

        return result.toString();
    }

    // 转义JSON字符串中的特殊字符
    private String escapeJsonString(String value) {
        if (value == null) {
            return "";
        }

        // 先转义反斜杠，再转义其他字符
        return value.replace("\\", "\\\\")
                .replace("\"", "\\\"")
                .replace("\b", "\\b")
                .replace("\f", "\\f")
                .replace("\n", "\\n")
                .replace("\r", "\\r")
                .replace("\t", "\\t");
    }

    // 转义JavaScript字符串中的特殊字符
    private String escapeJavaScriptString(String value) {
        if (value == null) {
            return "null";
        }

        String escaped = escapeJsonString(value);
        return "\"" + escaped + "\"";
    }

    // 安全的JavaScript回调方法
    public void callJavaScriptCallback(final String callbackFunction, final String result) {
        final Activity activity = activityRef.get();
        final WebView webView = webviewRef.get();

        if (activity == null || webView == null) {
            Log.w(TAG, "Activity or WebView is null, cannot callback JavaScript");
            return;
        }

        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    String jsCode = String.format("%s(%s)",
                            callbackFunction,
                            escapeJavaScriptString(result));

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                        // 使用更安全的evaluateJavascript方法
                        webView.evaluateJavascript(jsCode, null);
                    } else {
                        // 回退到loadUrl，但确保正确转义
                        String safeJsCode = "javascript:try{" + jsCode + ";}catch(e){console.error('NetUtil callback error:', e);}";
                        webView.loadUrl(safeJsCode);
                    }
                } catch (Exception e) {
                    Log.e(TAG, "JavaScript callback failed", e);
                }
            }
        });
    }

    // 添加HEAD请求方法
    @JavascriptInterface
    public void headAsync(final String urlString, final String callbackFunction) {
        if (!hasNetworkPermission()) {
            callJavaScriptCallback(callbackFunction, "{\"error\":\"No internet permission\"}");
            return;
        }

        NETWORK_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                final String result = headSync(urlString);
                callJavaScriptCallback(callbackFunction, result);
            }
        });
    }

    // 同步HEAD请求
    @JavascriptInterface
    public String headSync(String urlString) {
        if (!isValidUrl(urlString)) {
            return "{\"error\":\"Invalid URL\"}";
        }

        HttpURLConnection connection = null;
        Map<String, String> headers = new HashMap<>();

        try {
            URL url = new URL(urlString);
            connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法
            connection.setRequestMethod("HEAD");
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(10000);
            connection.setInstanceFollowRedirects(true);

            // 获取响应码和头部信息
            int responseCode = connection.getResponseCode();

            // 收集响应头
            for (int i = 0; ; i++) {
                String key = connection.getHeaderFieldKey(i);
                String value = connection.getHeaderField(i);
                if (key == null && value == null) {
                    break;
                }
                if (key != null) {
                    headers.put(key, value);
                }
            }

            // 构建包含响应头和状态码的JSON
            StringBuilder jsonResult = new StringBuilder();
            jsonResult.append("{\"statusCode\":").append(responseCode).append(",");
            jsonResult.append("\"headers\":{");

            boolean first = true;
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                if (!first) {
                    jsonResult.append(",");
                }
                jsonResult.append("\"").append(escapeJsonString(entry.getKey())).append("\":");
                jsonResult.append("\"").append(escapeJsonString(entry.getValue())).append("\"");
                first = false;
            }

            jsonResult.append("}}");
            return jsonResult.toString();
        } catch (Exception e) {
            Log.e(TAG, "HEAD request failed", e);
            return "{\"error\":\"" + escapeJsonString(e.getMessage()) + "\"}";
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    // 检查网络连接状态
    @JavascriptInterface
    public boolean isNetworkAvailable() {
        try {
            Context context = contextRef.get();
            if (context == null) return false;
            ConnectivityManager cm = (ConnectivityManager)
                    context.getSystemService(Context.CONNECTIVITY_SERVICE);
            if (cm != null) {
                NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
                return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "Network check failed", e);
            return false;
        }
    }

    // 获取网络缓存统计信息
    @JavascriptInterface
    public String getCacheStats() {
        try {
            JSONObject stats = new JSONObject();
            try {
                stats.put("cacheSize", responseCache.size());
                stats.put("maxSize", MAX_CACHE_SIZE);
                stats.put("totalRequests", totalRequests.get());
                stats.put("cacheHits", cacheHits.get());

                double hitRate = totalRequests.get() > 0 ?
                    (double) cacheHits.get() / totalRequests.get() * 100 : 0;
                stats.put("hitRate", Math.round(hitRate * 100.0) / 100.0);
            } catch (Exception jsonException) {
                Log.e(TAG, "JSON创建失败", jsonException);
                return "{\"error\":\"JSON creation failed: " + escapeJsonString(jsonException.getMessage()) + "\"}";
            }

            return stats.toString();
        } catch (Exception e) {
            Log.e(TAG, "Failed to get cache stats", e);
            return "{\"error\":\"" + escapeJsonString(e.getMessage()) + "\"}";
        }
    }

    // 清理网络缓存
    @JavascriptInterface
    public String clearCache() {
        try {
            int clearedCount = responseCache.size();
            responseCache.clear();
            totalRequests.set(0);
            cacheHits.set(0);

            JSONObject result = new JSONObject();
            try {
                result.put("success", true);
                result.put("clearedCount", clearedCount);
                result.put("message", "缓存已清空");
            } catch (Exception jsonException) {
                Log.e(TAG, "清理缓存JSON创建失败", jsonException);
                return "{\"success\":true,\"clearedCount\":" + clearedCount + ",\"message\":\"缓存已清空\"}";
            }

            return result.toString();
        } catch (Exception e) {
            Log.e(TAG, "Failed to clear cache", e);
            return "{\"success\":false,\"error\":\"" + escapeJsonString(e.getMessage()) + "\"}";
        }
    }

    // 获取缓存详情
    @JavascriptInterface
    public String getCacheDetails() {
        try {
            JSONArray cacheEntries = new JSONArray();

            for (Map.Entry<String, CachedResponse> entry : responseCache.entrySet()) {
                try {
                    JSONObject cacheEntry = new JSONObject();
                    cacheEntry.put("url", entry.getKey());
                    cacheEntry.put("timestamp", entry.getValue().getTimestamp());
                    cacheEntry.put("age", System.currentTimeMillis() - entry.getValue().getTimestamp());

                    // 添加响应预览（前100个字符）
                    String data = entry.getValue().getData();
                    if (data.length() > 100) {
                        cacheEntry.put("dataPreview", data.substring(0, 100) + "...");
                    } else {
                        cacheEntry.put("dataPreview", data);
                    }

                    cacheEntries.put(cacheEntry);
                } catch (Exception jsonException) {
                    Log.w(TAG, "缓存条目JSON创建失败: " + entry.getKey(), jsonException);
                    // 继续处理其他条目
                }
            }

            JSONObject result = new JSONObject();
            try {
                result.put("success", true);
                result.put("entries", cacheEntries);
                result.put("totalEntries", cacheEntries.length());
            } catch (Exception jsonException) {
                Log.e(TAG, "缓存详情结果JSON创建失败", jsonException);
                return "{\"success\":true,\"entries\":[],\"totalEntries\":0}";
            }

            return result.toString();
        } catch (Exception e) {
            Log.e(TAG, "Failed to get cache details", e);
            return "{\"success\":false,\"error\":\"" + escapeJsonString(e.getMessage()) + "\"}";
        }
    }

    // 清理过期缓存
    private void cleanupExpiredCache() {
        long currentTime = System.currentTimeMillis();
        AtomicInteger cleanedCount = new AtomicInteger();

        responseCache.entrySet().removeIf(entry -> {
            if (currentTime - entry.getValue().getTimestamp() > CACHE_EXPIRY_TIME) {
                cleanedCount.getAndIncrement();
                return true;
            }
            return false;
        });

        if (cleanedCount.get() > 0) {
            Log.i(TAG, "清理了 " + cleanedCount + " 个过期缓存项");
        }

        lastCleanupTime.set(currentTime);

        // 如果缓存过大，进行容量清理
        if (responseCache.size() > MAX_CACHE_SIZE) {
            performLRUCleanup();
        }
    }

    // LRU缓存清理
    private void performLRUCleanup() {
        if (responseCache.size() <= MAX_CACHE_SIZE) {
            return;
        }

        // 转换为列表进行排序（按时间戳排序，最老的在前）
        responseCache.entrySet().stream()
            .sorted(Map.Entry.comparingByValue((a, b) -> Long.compare(a.getTimestamp(), b.getTimestamp())))
            .limit(responseCache.size() - MAX_CACHE_SIZE)
            .forEach(entry -> responseCache.remove(entry.getKey()));

        Log.i(TAG, "LRU清理完成，缓存大小调整为: " + responseCache.size());
    }

    // 清理资源
    public void destroy() {
        NETWORK_EXECUTOR.shutdown();
        responseCache.clear();
        webviewRef.clear();
        activityRef.clear();
        contextRef.clear();
    }

    // ============ 缓存响应类 ============

    /**
     * 缓存响应包装类
     */
    private static class CachedResponse {
        private final String data;
        private final long timestamp;

        public CachedResponse(String data, long timestamp) {
            this.data = data;
            this.timestamp = timestamp;
        }

        public boolean isExpired(long maxAge) {
            return System.currentTimeMillis() - timestamp > maxAge;
        }

        public String getData() {
            return data;
        }

        public long getTimestamp() {
            return timestamp;
        }
    }
}